# -*- coding:utf8 -*-
import base64
import hashlib
import json
import os
import urllib
import urllib2
from django.conf.urls import url
import time
from wanbatvcom import utils
from wanbatvcom.http.whttp import send_error_response_on_exception, send_ok_response_with_data, \
    send_error_response_with_message, send_response_with_result
from wanbatvcom.settings import MEDIA_ROOT
from wanplus import config

from models import OttProgram, ProgramResource
from wanplus.utils import ReleaseStatus

__author__ = 'Forcs'

CONTENT_STATE_NO_SYNC = ReleaseStatus.NONE
CONTENT_STATE_PREVIEW = ReleaseStatus.PREVIEW
CONTENT_STATE_RELEASE = ReleaseStatus.RELEASE

OTT_RES = os.path.join(MEDIA_ROOT, "wanbaott/resources")
OTT_TEMP = os.path.join(MEDIA_ROOT, "wanbaott/temps")


class WanbaOttService(object):

    def __init__(self):
        self._name = 'wbo'

    @property
    def urls(self):

        def views_name(name):
            return '%s_%s' % (self._name, name)

        urlpatterns = [
            url(r'^resource/save$', self.save_resource, name=views_name("save_resource")),
            url(r'^media/save$', self.save_media, name=views_name("save_media")),
            url(r'^program/save$', self.save_program, name=views_name("save_program")),
            url(r'^program/preview/(?P<program_token>[0-9a-fA-F]{32,32})$', self.preview_program,
                name=views_name("preview_program")),
            url(r'^program/release/(?P<program_token>[0-9a-fA-F]{32,32})$', self.release_program,
                name=views_name("release_program")),
        ]
        return urlpatterns

    def save_program(self, request):
        def generate_code(id, token):
            return 'W%08d%s' % (id, token[-4:])

        body = request.POST
        title = body["title"]

        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(title.encode("utf8"), timestamp))
        token = md5.hexdigest()

        bgm_token = body["bgm"]
        media_token = body["media"]
        cover_n_hd_token = body["covernhd"]
        cover_h_fg_hd_token = body["coverhfghd"]

        resource_tokens = list()
        # 记录资源路径
        resource_tokens.append(bgm_token)
        resource_tokens.append(cover_n_hd_token)
        resource_tokens.append(cover_h_fg_hd_token)
        # 生成资源配置文件
        resource_config = {
            "title": title.encode("utf8"),
            "token": token,
            "bgm": bgm_token,
            "media": media_token,
            "cover": {
                "hd": {
                    "normal_foreground": cover_n_hd_token,
                    "highlight_foreground": cover_h_fg_hd_token,
                },
                "fhd": {
                    "normal_foreground": cover_n_hd_token,
                    "highlight_foreground": cover_h_fg_hd_token,
                },
                "uhd": {
                    "normal_foreground": cover_n_hd_token,
                    "highlight_foreground": cover_h_fg_hd_token,
                }
            }
        }

        file_paths = list()
        for res_token in resource_tokens:
            if not res_token:
                continue
            try:
                model = ProgramResource.objects.get(token=res_token)
                model.program_token = token
                file_paths.append(MEDIA_ROOT + model.local_path)
                model.save()
            except Exception as e:
                return send_error_response_on_exception(e)
        # 保存视频资源的节目标识
        try:
            media_res = ProgramResource.objects.get(token=media_token)
            media_res.program_token = token
            media_res.save()
        except Exception as e:
            return send_error_response_on_exception(e)

        import zipfile
        # 创建临时资源包文件
        resource_package_name = os.path.join(OTT_TEMP, token + ".zip")
        z = zipfile.ZipFile(resource_package_name, "w")
        md5 = hashlib.md5()
        for file_path in file_paths:
            # 打包
            z.write(file_path, token + "/" + os.path.splitext(os.path.basename(file_path))[0])
            # 更新签名
            md5.update(file(file_path).read())

        # 生成MD5签名
        resource_config["md5"] = md5.hexdigest()
        config_file_name = os.path.join(OTT_TEMP, "config.ini")
        config_file = open(config_file_name, "w")
        config_file.write(json.dumps(resource_config, encoding='utf8', indent=2))
        config_file.close()
        # 将配置文件打包
        z.write(config_file_name, token + "/" + os.path.basename(config_file_name))
        z.close()
        # 删除临时文件
        os.remove(config_file_name)
        # 将资源包上传到cdn
        upload_ok, msg = utils.upload_to_ftp(os.path.basename(resource_package_name),
                                             src_path=OTT_TEMP,
                                             dest_path="wanbaott/wbrp",
                                             host="upload.sihuacdn.com",
                                             user="wanbatv",
                                             password="wanbatv_upload")

        if upload_ok:
            try:
                program, created = OttProgram.objects.get_or_create(token=token)
                program.title = title
                program.bgm = bgm_token
                program.media = media_token
                program.cover_n_hd = cover_n_hd_token
                program.cover_h_fg_hd = cover_h_fg_hd_token
                program.cover_n_fhd = cover_n_hd_token
                program.cover_h_fg_fhd = cover_h_fg_hd_token
                program.wrp_url = "/" + msg
                if created:
                    program.code = generate_code(program.id, token)
                program.save()
            except Exception as e:
                return send_error_response_on_exception(e)

            return send_ok_response_with_data({
                "token": token,
            }, message='打包成功')
        else:
            return send_error_response_with_message(msg)

    def save_media(self, request):
        import logging
        logger = logging.getLogger("wanba")

        print(u'save media ==>')
        form_file = request.FILES
        print(u'save media get form file')
        try:
            file_object = form_file["file"]
        except Exception as e:
            return send_error_response_on_exception(e)
        fn = file_object.name
        suffix = fn.split(".")[1]
        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(fn.encode("utf8"), timestamp))
        file_name_encode = md5.hexdigest()
        print(u'begin save media %s' % file_name_encode)
        logger.info(u'begin save media %s' % file_name_encode)
        result, file_name, local_name = utils.upload_file(file_object, file_name=file_name_encode,
                                                          file_suffix=suffix, root_dir="wanbaott/temps")
        print(u'save media %s to %s' % (file_name_encode, local_name))
        logger.info(u'save media %s to %s' % (file_name_encode, local_name))
        from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_audio
        md5 = hashlib.md5()
        md5.update("{}{}".format(file_name_encode, timestamp))
        bgm_file_name = md5.hexdigest()
        bgm_file_local = os.path.join(OTT_RES, bgm_file_name) + ".mp3"
        ffmpeg_extract_audio(local_name, bgm_file_local)
        print(u'extract audio %s' % bgm_file_local)
        logger.info(u'extract audio %s' % bgm_file_local)
        upload_ok, msg = utils.upload_to_ftp(file_name_encode + "." + suffix,
                                             src_path=OTT_TEMP,
                                             dest_path="wanbaott/video",
                                             host="upload.sihuacdn.com",
                                             user="wanbatv",
                                             password="wanbatv_upload")
        print(u'upload to cdn, result %s %s' % (upload_ok, msg))
        logger.info(u'upload to cdn, result %s %s' % (upload_ok, msg))
        if not upload_ok:
            return send_error_response_with_message(message=u'上传视频失败 %s' % msg)

        if os.path.exists(local_name):
            os.remove(local_name)

        from models import ProgramResource
        try:
            bgm_res = ProgramResource()
            bgm_res.token = bgm_file_name
            bgm_res.local_path = "/wanbaott/resources/" + os.path.basename(bgm_file_local)
            bgm_res.save()

            media_res = ProgramResource()
            media_res.token = file_name_encode
            media_res.local_path = "/" + msg
            media_res.save()
        except Exception as e:
            return send_error_response_on_exception(e)

        from wanbatvcom.settings import MEDIA_URL
        if result:
            return send_ok_response_with_data(data={
                "media_filename": MEDIA_URL + file_name,  # /media/[root_dir]/[token].[png|jpg]
                "media_token": file_name_encode,
                "bgm_filename": bgm_file_local,
                "bgm_token": bgm_file_name
            })
        else:
            return send_error_response_with_message(u'保存文件失败')

    def save_resource(self, request):
        form_file = request.FILES
        file_object = form_file["file"]
        fn = file_object.name
        suffix = fn.split(".")[1]
        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(fn.encode("utf8"), timestamp))
        file_name_encode = md5.hexdigest()
        result, file_name, local_name = utils.upload_file(file_object, file_name=file_name_encode,
                                                          file_suffix=suffix, root_dir="wanbaott/resources")

        from models import ProgramResource
        try:
            resource = ProgramResource()
            resource.token = file_name_encode
            resource.local_path = "/" + file_name
            resource.save()
        except Exception as e:
            return send_error_response_on_exception(e)

        from wanbatvcom.settings import MEDIA_URL
        if result:
            return send_ok_response_with_data(data={
                "filename": MEDIA_URL + file_name,  # /media/[root_dir]/[token].[png|jpg]
                "token": file_name_encode
            })
        else:
            return send_error_response_with_message(u'保存文件失败')

    def preview_program(self, request, program_token):
        return self._sync_program(request, config.PREVIEW_HOST, program_token)

    def release_program(self, request, program_token):
        return self._sync_program(request, config.RELEASE_HOST, program_token)

    def _sync_program(self, reuqest, host=None, program_token=None):

        data = dict()
        try:
            ott_program = OttProgram.objects.get(token=program_token)
            media_res = ProgramResource.objects.get(token=ott_program.media)
            data["title"] = ott_program.title.encode("utf8")
            data["media"] = media_res.local_path
            data["bgm"] = ott_program.bgm
            data["covernhd"] = ott_program.cover_n_hd
            data["coverhfghd"] = ott_program.cover_h_fg_hd
            data["covernfhd"] = ott_program.cover_n_fhd
            data["coverhfgfhd"] = ott_program.cover_h_fg_fhd
            data["wrpurl"] = ott_program.wrp_url
        except Exception as e:
            return send_error_response_on_exception(e)

        try:
            req = urllib2.Request("http://%s/api/bengbengtiao/program/sync/%s" % (host, program_token))
            res = urllib2.urlopen(req, urllib.urlencode(data))
            res_content = res.read()
            res.close()

            if host == config.PREVIEW_HOST:
                ott_program.sync_state = CONTENT_STATE_PREVIEW
            elif host == config.RELEASE_HOST:
                ott_program.sync_state = CONTENT_STATE_RELEASE
            ott_program.save()

            return send_response_with_result(json.dumps(json.loads(res_content, encoding="utf8")))
        except Exception as e:
            return send_error_response_on_exception(e)

wanba_ott_service = WanbaOttService()
